package com.zhongkun.datahome.service.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhongkun.datahome.common.exception.ServiceException;
import com.zhongkun.datahome.common.utils.DateUtils;
import com.zhongkun.datahome.core.domain.vo.UserBaseVo;
import com.zhongkun.datahome.core.mapper.SysUserMapper;
import com.zhongkun.datahome.core.repository.SysDictDataRepository;
import com.zhongkun.datahome.core.repository.TenantUserRepository;
import com.zhongkun.datahome.service.constant.DataAssetsShowScopeEnum;
import com.zhongkun.datahome.service.constant.EntityTypeEnum;
import com.zhongkun.datahome.service.constant.SwitchEnum;
import com.zhongkun.datahome.service.constant.SysDictTypeEnum;
import com.zhongkun.datahome.service.constant.YesOrNoEnum;
import com.zhongkun.datahome.service.domain.CommonFile;
import com.zhongkun.datahome.service.domain.DataAssets;
import com.zhongkun.datahome.service.domain.HouseAssetsRelation;
import com.zhongkun.datahome.service.mapper.CustomerHouseMapper;
import com.zhongkun.datahome.service.mapper.DataAssetsMapper;
import com.zhongkun.datahome.service.repository.CommonFileRepository;
import com.zhongkun.datahome.service.repository.DataAssetsRepository;
import com.zhongkun.datahome.service.repository.HouseAssetsRelationRepository;
import com.zhongkun.datahome.service.req.cmd.assets.DataAssetsCmd;
import com.zhongkun.datahome.service.req.cmd.assets.UnbindDataAssetsCmd;
import com.zhongkun.datahome.service.req.qry.assets.DataAssetsQry;
import com.zhongkun.datahome.service.res.CommonFileVo;
import com.zhongkun.datahome.service.res.PageVo;
import com.zhongkun.datahome.service.res.assets.DataAssetsVo;
import com.zhongkun.datahome.service.service.IDataAssetsService;
import com.zhongkun.datahome.service.service.IFileService;
import com.zhongkun.datahome.service.service.ISystemSettingService;
import com.zhongkun.datahome.service.utils.StreamUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 数字资产Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-04-14
 */
@Service
public class DataAssetsServiceImpl implements IDataAssetsService {
    @Resource
    private CommonFileRepository commonFileRepository;

    @Resource
    private DataAssetsRepository dataAssetsRepository;

    @Resource
    private DataAssetsMapper dataAssetsMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private HouseAssetsRelationRepository houseAssetsRelationRepository;

    @Resource
    private IFileService fileService;

    @Resource
    private TenantUserRepository tenantUserRepository;

    @Resource
    private ISystemSettingService systemSettingService;


    @Override
    public PageVo<DataAssetsVo> page(DataAssetsQry qry) {
        IPage<Long> pageResult = dataAssetsMapper.pageIds(new Page<>(qry.getPageNo(), qry.getPageSize()), qry);
        if (CollectionUtils.isEmpty(pageResult.getRecords())) {
            return PageVo.emptyPage(qry.getPageNo(), qry.getPageSize());
        }

        List<DataAssetsVo> records = dataAssetsMapper.getList(DataAssetsQry.of(pageResult.getRecords()));

        // 操作人
        tenantUserRepository.batchSetUserName(records, DataAssetsVo::getUpdateBy, DataAssetsVo::setOperatorName);

        systemSettingService.batchSetDataSettingName(records, DataAssetsVo::getGroupTypeId, DataAssetsVo::setGroupTypeName);
        return new PageVo<>(records, qry.getPageNo(), qry.getPageSize(), pageResult.getTotal());
    }

    @Override
    public List<DataAssetsVo> listByHouseId(DataAssetsQry qry) {
        List<DataAssets> houseDataAssets = dataAssetsMapper.listByHouseId(qry);
        // 如果需要展示 对全部房号可见的 资产，这里需要追加查询showScope=2的资产
        List<DataAssets> allShowDataAssets = dataAssetsRepository.listAllShowAssets(qry.getGroupTypeId(), qry.getAssetsStatus());

        List<DataAssets> allDataAssetsList = Stream.concat(houseDataAssets.stream(), allShowDataAssets.stream())
                .sorted(Comparator.comparing(DataAssets::getUpdateTime).reversed())
                .collect(Collectors.toList());

        List<String> dataAssetsIds = allDataAssetsList.stream()
                .map(item -> item.getId().toString())
                .collect(Collectors.toList());

        List<CommonFile> commonFiles = commonFileRepository.listByDataAssetsIds(dataAssetsIds, EntityTypeEnum.ASSETS_FILE);
        Map<String, List<CommonFile>> fileGroupMap = StreamUtil.listGroupBy(commonFiles, CommonFile::getEntityId);

        return allDataAssetsList.stream().map(item -> DataAssetsVo.convert(item, fileGroupMap)).collect(Collectors.toList());
    }

    @Override
    public DataAssetsVo getInfo(Long id) {
        DataAssetsQry qry = new DataAssetsQry();
        qry.setAssetsId(id);
        List<DataAssetsVo> list = dataAssetsMapper.getList(qry);

        DataAssetsVo dataAssetsVo = list.stream()
                .findFirst()
                .orElseThrow(() -> new ServiceException("数字资产不存在"));

        List<CommonFile> commonFiles = commonFileRepository.listByDataAssetsIds(Collections.singletonList(dataAssetsVo.getId().toString()), EntityTypeEnum.ASSETS_FILE);

        List<CommonFileVo> commonFileVos = commonFiles.stream()
                .map(CommonFileVo::convert)
                .sorted(Comparator.comparing(CommonFileVo::getId).reversed())
                .collect(Collectors.toList());
        dataAssetsVo.setFileVoList(commonFileVos);
        return dataAssetsVo;
    }

    @Override
    @Transactional
    public Long add(DataAssetsCmd cmd) {
        // 支持批量保存
        if (YesOrNoEnum.YES.is(cmd.getBatchSaveFlag())) {
            if (CollectionUtils.isNotEmpty(cmd.getBatchSaveEntities())) {
                cmd.getBatchSaveEntities().stream()
                        .map(item -> DataAssetsCmd.of(cmd, item))
                        .forEach(this::addData);
            }
            return 0L;
        }

        return addData(cmd);
    }

    private Long addData(DataAssetsCmd cmd) {
        DataAssets dataAssets = DataAssets.of(cmd);
        dataAssetsRepository.save(dataAssets);

        // 保存文件
        batchSaveAssetsFile(cmd, dataAssets);

        // 保存可见房号
        batchSaveAssetsRelation(cmd, dataAssets);
        return dataAssets.getId();
    }

    @Override
    @Transactional
    public void edit(DataAssetsCmd cmd) {
        DataAssets dataAssets = dataAssetsRepository.getById(cmd.getId());
        if (Objects.isNull(dataAssets)) {
            throw new ServiceException("数字资产不存在");
        }

        dataAssets.update(cmd);
        dataAssetsRepository.updateById(dataAssets);

        // 删除老的
        commonFileRepository.removeByAssetsId(Collections.singletonList(cmd.getId().toString()));
        // 保存新的
        batchSaveAssetsFile(cmd, dataAssets);

        // 保存关系
        houseAssetsRelationRepository.removeByAssetsId(dataAssets.getId());
        batchSaveAssetsRelation(cmd, dataAssets);
    }

    private void batchSaveAssetsFile(DataAssetsCmd cmd, DataAssets dataAssets) {
        // 老的用这个
        if (CollectionUtils.isNotEmpty(cmd.getUrls())) {
            List<CommonFile> assetsFiles = cmd.getUrls().stream()
                    .map(item -> CommonFile.convertDataAssetsFile(dataAssets.getId(), item, dataAssets.getAssetsTitle()))
                    .peek(item -> item.setFileSize(fileService.getFileSize(item.getFileUrl())))
                    .collect(Collectors.toList());
            commonFileRepository.saveBatch(assetsFiles);
        }

        // 新的用这个
        if (CollectionUtils.isNotEmpty(cmd.getFileEntityList())) {
            List<CommonFile> assetsFiles = cmd.getFileEntityList().stream()
                    .map(item -> CommonFile.convertDataAssetsFile(dataAssets.getId(), item, dataAssets.getAssetsTitle()))
                    .peek(item -> item.setFileSize(fileService.getFileSize(item.getFileUrl())))
                    .collect(Collectors.toList());
            commonFileRepository.saveBatch(assetsFiles);
        }
    }

    private void batchSaveAssetsRelation(DataAssetsCmd cmd, DataAssets dataAssets) {
        if (DataAssetsShowScopeEnum.PART_SHOW.is(cmd.getShowScope()) && CollectionUtils.isNotEmpty(cmd.getHouseIds())) {
            List<HouseAssetsRelation> relationList = cmd.getHouseIds().stream()
                    .map(item -> HouseAssetsRelation.of(item, dataAssets.getId()))
                    .collect(Collectors.toList());
            houseAssetsRelationRepository.saveBatch(relationList);
        }
    }

    @Override
    public void remove(List<Long> ids) {
        if (CollectionUtils.isNotEmpty(ids)) {
            dataAssetsRepository.removeBatchByIds(ids);
        }
    }

    @Override
    public void unbind(UnbindDataAssetsCmd cmd) {
        houseAssetsRelationRepository.removeBy(cmd.getHouseId(), cmd.getDataAssetsId());
    }

    @Override
    public void changeStatus(DataAssetsCmd cmd) {
        DataAssets dataAssets = dataAssetsRepository.getById(cmd.getId());
        if (Objects.isNull(dataAssets)) {
            throw new ServiceException("数字资产不存在");
        }

        dataAssets.setAssetsStatus(SwitchEnum.getStatus(cmd.getAssetsStatus()));
        dataAssetsRepository.updateById(dataAssets);
    }
}
